/** ---------- 地图初始化 和 图层渲染 mixin  FOR AMAP 高德 ---------- */
import Vue from 'vue'
import MapMarker from '@/components/map/overflow/MapMarker.vue' // 标记
const MyMapMarker = Vue.extend(MapMarker)
let MAP_INSTANCE = null // 地图实例
/**
 * MAP_OVERFLOWS [Object] 覆盖物存储 用于动态删除
 * e.g.
 *    { 1: { normal: [], cluster: [], heatmap:[] }, 2: {}, 3: {}, 999: detail }
 *    1,2,3 级别  999详情标记，属于<标记>，但与<标记>不同的是只会存在一个，清除逻辑不一致
 *    MAP_DEFAULT_LEVEL_TYPES
 *      'normal': 标记、多边形、线
 *      'cluster': 聚合
 *      'heatmap': 热力图
 */
const MAP_OVERFLOWS = { 2: { normal: [], cluster: [], heatmap: [] }, 999: null }
const MAP_MARKER_EXTENDS = { 2: [], 999: [] } // MyMapMarker 实例容器 {<level>: [new, new, ...]}
const MAP_MARKER_ZINDEX = 12 // 默认覆盖物ZINDEX
const MAP_DEFAULT_LEVEL = 2 // 默认覆盖物（清除）级别
const MAP_DETAIL_ALEVEL = [999, 'detail']
const MAP_DEFAULT_LEVEL_TYPES = ['normal', 'cluster', 'heatmap']
export default {
  data () {
    return {
      mapIsReady: true // 地图是否准备就绪
    }
  },
  methods: {
    // ********** 地图 初始化&事件&通用方法 **********
    // 初始化地图
    mapInit () {
      const map = new AMap.Map('myMap', {
        center: [112.983048, 28.178239],
        layers: [
          // 路网
          // new AMap.TileLayer.RoadNet(),
          // 卫星
          new AMap.TileLayer.Satellite()
        ],
        showLabel: false,
        zoom: 17,
        rotateEnable: true,
        pitchEnable: true,
        viewMode: '3D', // 开启3D视图,默认为关闭
        pitch: 40,
        animateEnable: false // 地图平移过程中是否使用动画
      })
      MAP_INSTANCE = map
      window.MAP_INSTANCE = map
      // 定义地图事件
      this.mapEvents()
    },
    // ********** 地图 事件/交互 相关函数 **********
    // 地图事件
    mapEvents () {
      if (MAP_INSTANCE) {
        MAP_INSTANCE.on('zoomend', (ev) => {
          // console.log('>>>>>>>>>> getZoom：', MAP_INSTANCE.getZoom())
          this.zoomChanged(MAP_INSTANCE.getZoom())
        })
        MAP_INSTANCE.on('click', (ev) => {
          if (ev.lnglat) {
            console.log('经纬度：', `${ev.lnglat.getLng()},${ev.lnglat.getLat()}`)
          }
        })
      }
    },
    // 设置层级
    mapSetZoom (val) {
      MAP_INSTANCE.setZoom(val)
    },
    /**
     * 设置中心点
     * @param {Array} val 经纬度 [lng, lat]
     * @param {Array} move 移动差值 [lng-move, lat-move] 正值为向 右&上，反之
     */
    mapSetCenter (val, move) {
      const _move = this.getCenterLatIns(move)
      MAP_INSTANCE.setCenter([val[0] + _move[0], val[1] + _move[1]])
    },
    // 获取纬度的偏移 （为中心点服务）
    getCenterLatIns (move) {
      if (move === undefined || move == null || move.length < 2) { return [0, 0] }
      const bounds = MAP_INSTANCE.getBounds()
      return [(bounds.southWest.lng - bounds.northEast.lng) * move[0], (bounds.southWest.lat - bounds.northEast.lat) * move[1]]
    },

    // ********** 地图 图层相关函数 **********
    /**
     * 地图标记详情，属于<标记>，但与<标记>不同的是只会存在一个，清除逻辑不一致
     * @param {Object} data 数据
     * @param {String} data.component 组件
     * @param {Object} data.data 数据
     * @param {Number} data.move 移动ins
     */
    mapMarkerDetail (data) {
      if (data && data.data) {
        const lng = Number(data.longitude)
        const lat = Number(data.latitude)
        if (lng > 0 && lat > 0) {
          let marker = null
          const position = new AMap.LngLat(lng, lat)
          const panelDom = new MyMapMarker({
            data: {
              data: data.data,
              component: data.component
            },
            methods: {
            }
          })
          marker = new AMap.Marker({
            zIndex: 9999999999,
            position: position,
            content: panelDom.$mount().$el
            // topWhenClick: true // 鼠标点击时marker是否置顶，默认false ，不置顶
          })
          this.mapSetMarkerExtend(panelDom, MAP_DETAIL_ALEVEL[0])
          MAP_INSTANCE.add([marker])
          // 覆盖物事件绑定处理 只有 move
          data.click = false
          data.hover = null
          this.mapOverflowEvents(marker, data, {}, {})
          this.mapSetOverflow([marker], MAP_DETAIL_ALEVEL[0], MAP_DETAIL_ALEVEL[1]) // see MAP_DETAIL_ALEVEL = [999, 'detail']
        }
      }
    },
    /**
     * 标记
     * @param {Object} data 数据
     * @param {String} data.component 组件
     * @param {Array} data.list 列表
     * @param {Nmuber} data.level 级别 1/2/3
     * @param {Nmuber} data.zIndex zIndex
     * @param {Number} data.move 移动ins
     */
    mapMarkers (data) {
      const markers = []
      for (let index = 0; index < data.list.length; index++) {
        const obj = data.list[index]
        const lng = Number(obj.longitude)
        const lat = Number(obj.latitude)
        if (lng > 0 && lat > 0) {
          let marker = null
          const position = new AMap.LngLat(lng, lat)
          const panelDom = new MyMapMarker({
            data: {
              data: obj,
              component: data.component
            },
            methods: {
            }
          })
          marker = new AMap.Marker({
            position: position,
            // content: panelDom,
            content: panelDom.$mount().$el,
            zIndex: data.zIndex ? data.zIndex : MAP_MARKER_ZINDEX
            // topWhenClick: true // 鼠标点击时marker是否置顶，默认false ，不置顶
          })
          this.mapSetMarkerExtend(panelDom, data.level)
          // panelDom.$destroy()
          // 覆盖物事件绑定处理 只有 move
          data.click = false
          data.hover = null
          this.mapOverflowEvents(marker, data, obj, {})
          markers.push(marker)
        }
      }
      if (markers && markers.length > 0) {
        // 将 markers 添加到地图
        MAP_INSTANCE.add(markers)
        this.mapSetOverflow(markers, data.level, MAP_DEFAULT_LEVEL_TYPES[0]) // normal
      }
    },
    /**
     * 多边形
     * @param {Object} data 数据
     * @param {Array} data.list 列表
     * @param {Nmuber} data.level 级别 1/2/3
     * @param {Boolean} data.click 点击事件，eventDataHandler
     * @param {Object} data.option 自定义的图形属性，如有不同则可定义多组多边形，如 this.$storeCommit('MD', { list: [{ Polygons1 }, { Polygons2 }, ...]
     * @param {Object} data.hover hover事件，改变覆盖物属性的属性，如有不同则可定义多组多边形
     * @param {Number} data.move 移动ins
     */
    mapPolygons (data) {
      const polygons = []
      for (let index = 0; index < data.list.length; index++) {
        const obj = data.list[index]
        const _options = Object.assign({
          path: obj.paths,
          strokeColor: '#ffffff',
          strokeWeight: 2,
          strokeOpacity: 0.8,
          fillOpacity: 0.4,
          fillColor: '#1791fc',
          // zIndex: 50,
          bubble: true
        }, data.option)
        const polygon = new AMap.Polygon(_options)
        // 覆盖物事件绑定处理
        this.mapOverflowEvents(polygon, data, obj, _options)
        polygons.push(polygon)
      }
      if (polygons && polygons.length > 0) {
        // 将 polygons 添加到地图
        MAP_INSTANCE.add(polygons)
        // 将覆盖物放入容器（级别）
        this.mapSetOverflow(polygons, data.level, MAP_DEFAULT_LEVEL_TYPES[0]) // normal
      }
    },
    /**
     * 折线
     * @param {Object} data 数据
     * @param {Array} data.list 列表
     * @param {Nmuber} data.level 级别 1/2/
     * @param {Boolean} data.click 点击事件，eventDataHandler
     * @param {Object} data.option 自定义的图形属性，如有不同则可定义多组折线，如 this.$storeCommit('MD', { list: [{ Polylines1 }, { Polylines2 }, ...]
     * @param {Object} data.hover hover事件，改变覆盖物属性的属性，如有不同则可定义多组折线
     * @param {Number} data.move 移动ins
     * @param {Number} data.moves 移动的中心点位
     */
    mapPolylines (data) {
      const polylines = []
      for (let index = 0; index < data.list.length; index++) {
        const obj = data.list[index]
        const _options = Object.assign({
          path: obj.paths,
          zIndex: data.zIndex ? data.zIndex : 10,
          strokeWeight: 8,
          strokeColor: '#43DA2D',
          strokeOpacity: 0.8,
          isOutline: true,
          borderWeight: 2,
          outlineColor: '#ffeeff',
          geodesic: true
        }, data.option)
        const polyline = new AMap.Polyline(_options)
        // 覆盖物事件绑定处理
        this.mapOverflowEvents(polyline, data, obj, _options)
        polylines.push(polyline)
      }
      if (polylines && polylines.length > 0) {
        // 将 polygons 添加到地图
        MAP_INSTANCE.add(polylines)
        // 将覆盖物放入容器（级别）
        this.mapSetOverflow(polylines, data.level, MAP_DEFAULT_LEVEL_TYPES[0]) // normal
      }
    },
    /**
     * 聚合层  ----> 在 MapHandler.vue 定义聚合图层样式
     * @param {Object} data 数据
     * @param {String} data.category 类型 e.g. 'qiye' 、'point'
     * @param {Nmuber} data.level 级别 1/2/
     * @param {Array} data.list 列表
     * @param {Array} data.list[n]._category marker的类型（没有时默认为data.category）
     * @param {Number} data.maxZoom 最大的聚合级别
     * @param {Number} data.gridSize 聚合计算时网格的像素大小
     * @param {Boolean} data.click 点击事件
     */
    mapLayerCluster (data) {
      // console.log('>>>>>>>>>> mapLayerCluster：', data)
      data.list.map(item => {
        item.lnglat = [`${item.longitude}`, `${item.latitude}`]
      })
      let cursor = 'default'// cursor: pointer;
      if (data.click) { cursor = 'pointer' }
      const _category = data.category
      const _renderMarker = function (context) {
        context.marker.setContent(
          `<div class="amap-cluster-main">
            <div class="amap-cluster-${_category}" style="cursor: ${cursor};"></div>
          </div>`
        )
        if (context.data && context.data.length > 0) {
          context.marker.setExtData(context.data[0])
        }
        context.marker.setOffset(new AMap.Pixel(0, 0))
      }
      const _renderClusterMarker = function (context) {
        var str =
          `<div class="amap-cluster-main">
            <div class="amap-cluster-${_category}" style="cursor: ${cursor};">
              <span>${context.count}</span>
            </div>
          </div>`
        context.marker.setContent(str)
        context.marker.setOffset(new AMap.Pixel(0, 0))
      }
      // MAP_CLUSTER_LAYER
      const clusterLayer = new AMap.MarkerCluster(MAP_INSTANCE, data.list, {
        renderClusterMarker: _renderClusterMarker, // 自定义聚合点样式
        renderMarker: _renderMarker, // 自定义非聚合点样式
        gridSize: data.gridSize ? data.gridSize : 100, // 聚合计算时网格的像素大小，默认60
        maxZoom: data.maxZoom ? data.maxZoom : 16 // 最大的聚合级别，大于该级别就不进行相应的聚合，默认值为 18
      })
      // 聚合事件绑定处理 只有 click
      data.move = null
      data.hover = false
      this.mapOverflowEvents(clusterLayer, data, {}, {})
      this.mapSetOverflow([clusterLayer], data.level, MAP_DEFAULT_LEVEL_TYPES[1])
    },
    /**
     * 热力图
     * @param {Object} data 数据
     * @param {Object} data.options 参数
     * @param {Nmuber} data.level 级别 1/2/
     * @param {Array|null} data.list 数据 null则是清空
     */
    mapHeatmap (data) {
      if (data.list && data.list.length > 0) {
        MAP_INSTANCE.plugin(['AMap.HeatMap'], () => {
          // 初始化heatmap对象
          const heatmap = new AMap.HeatMap(MAP_INSTANCE, Object.assign({
            radius: 50, // 给定半径
            opacity: [0.8, 0.9],
            zIndex: 12,
            gradient: {
              0.2: 'rgb(0, 255, 255)',
              0.5: 'rgb(0, 110, 255)',
              0.8: 'rgb(100, 0, 255)'
            }
          }, data.options))
          // 设置数据集：该数据为北京部分“公园”数据
          heatmap.setDataSet({
            data: data.list,
            max: 100
          })
          this.mapSetOverflow([heatmap], data.level, MAP_DEFAULT_LEVEL_TYPES[2])
        })
      }
    },

    /**
     * 覆盖物事件绑定处理
     * @param {Object} overflow 覆盖物，单个
     * @param {Object} data 数据配置 { type: '00010', click, hover...}
     * @param {Boolean} data.click 点击事件，eventDataHandler
     * @param {Object} data.hover hover事件，改变覆盖物属性的属性
     * @param {Number} data.move 移动ins
     * @param {Object|Array} obj 数据对象
     * @param {Object} option 覆盖物参数
     */
    mapOverflowEvents (overflow, data, obj, option) {
      // console.log('>>>>>>>>>> mapOverflowEvents：', data)
      // 移动
      if (data.move !== undefined && data.move != null) {
        const lng = Number(obj.longitude)
        const lat = Number(obj.latitude)
        if (lng > 0 && lat > 0) {
          this.mapSetCenter([lng, lat], data.move)
        }
      }
      if (data.moves && data.moves.length) {
        this.mapSetCenter([data.moves[0], data.moves[1]], data.move)
      }
      // 点击事件
      if (data.click) {
        overflow.on('click', (event) => {
          // console.log(event.target.className)
          // Overlay.Polyline
          // if (event.target.className === '') {
          // }
          if (event.cluster) {
            // 说明是聚合
            let clusterData = event.clusterData
            if (!clusterData || clusterData.length <= 0) {
              // 聚合为空则说明点击的是聚合的标记，则从标记中取
              const mkd = event.marker && event.marker.getExtData()
              if (mkd) {
                clusterData = [mkd]
              }
            }
            obj = clusterData
          }
          // console.log('>>>>>>>>>> obj：', obj)
          this.eventDataHandler({
            type: data.type,
            eventType: 'click',
            lnglat: [event.lnglat.getLng(), event.lnglat.getLat()],
            // data: event.target.getExtData()
            data: obj
          }, event)
        })
      }
      // hover事件，根据hover值改变覆盖物属性
      if (data.hover) {
        // console.log('>>>>>>>>>> data.hover：', data.hover)
        overflow.on('mouseover', (event) => {
          const _ops = Object.assign({}, option, data.hover)
          overflow.setOptions(_ops)
        }).on('mouseout', (event) => {
          overflow.setOptions(option)
        })
      }
    },

    /**
     * 将Marker实例根据级别放入容器
     * @param {Object}} instance new MapMarker() vue实例
     * @param {Number} level 存储级别
     */
    mapSetMarkerExtend (instance, level) {
      if (level == null || level === undefined) { level = MAP_DEFAULT_LEVEL } // 默认为2
      if (!MAP_MARKER_EXTENDS[level]) {
        MAP_MARKER_EXTENDS[level] = []
      }
      MAP_MARKER_EXTENDS[level].push(instance)
      // console.log('>>>>>>>>>> MAP_MARKER_EXTENDS：', MAP_MARKER_EXTENDS)
    },
    /**
     * 将覆盖物根据级别放入容器
     * @param {Array} list 覆盖物数组
     * @param {Number} level 存储级别
     * @param {String} type 类型 see MAP_DEFAULT_LEVEL_TYPES = ['normal', 'cluster', 'heatmap']
     */
    mapSetOverflow (list, level, type) {
      if (level == null || level === undefined) { level = MAP_DEFAULT_LEVEL } // 默认为2
      if (!type) { type = MAP_DEFAULT_LEVEL_TYPES[0] } // 默认为normal
      // MAP_OVERFLOWS { 2: { normal: [], cluster: [], heatmap: [] }, 999: null }
      if (!MAP_OVERFLOWS[level]) {
        MAP_OVERFLOWS[level] = {}
      }
      if (!MAP_OVERFLOWS[level][type]) {
        MAP_OVERFLOWS[level][type] = []
      }
      MAP_OVERFLOWS[level][type] = MAP_OVERFLOWS[level][type].concat(list)
    },

    /**
     * 清除地图
     * @param {Number|Array} clearLevel 清除级别 ，默认2 see MAP_DEFAULT_LEVEL
     *  Number
     *  0不清除
     *  1清除级别1的，主要用于如企业周围点位展示等
     *  2清除级别1和2的，默认清除级别，如企业分布，切换分类需要清除的
     *  3清除级别1、2和3的，主要用于如城市安全交警单位等，切换分类不需要清除的
     *  100清除所有，主要用于如 切换板块等
     *  101只清除详情窗口
     *
     *  Array
     *  clearLevel[0]覆盖物清除级别  clearLevel[1]是否清除详情窗口
     * @example 只清除详情窗口: [0, true]
     */
    mapClear (clearLevel) {
      if (!MAP_INSTANCE) { return false }
      // 默认清除详情窗口
      let clearDetail = true
      if (clearLevel == null || clearLevel === undefined) {
        // 默认清除级别
        clearLevel = MAP_DEFAULT_LEVEL
      } else if (Array.isArray(clearLevel)) {
        // clearLevel[0]覆盖物清除级别  clearLevel[1]是否清除详情窗口
        clearLevel = clearLevel[0]
        clearDetail = clearLevel[1]
      }
      // 清除详情窗口 MAP_DETAIL_ALEVEL = [999, 'detail']  => MAP_OVERFLOWS { 999: { 'detail': [] } }
      if (clearDetail) {
        // MAP_DETAIL_LEVEL
        if (MAP_OVERFLOWS[MAP_DETAIL_ALEVEL[0]] && MAP_OVERFLOWS[MAP_DETAIL_ALEVEL[0]][MAP_DETAIL_ALEVEL[1]]) {
          MAP_INSTANCE.remove(MAP_OVERFLOWS[MAP_DETAIL_ALEVEL[0]][MAP_DETAIL_ALEVEL[1]])
          MAP_OVERFLOWS[MAP_DETAIL_ALEVEL[0]][MAP_DETAIL_ALEVEL[1]] = []
        }
        // detail 清除详情的marker vue实例
        if (MAP_MARKER_EXTENDS[MAP_DETAIL_ALEVEL[0]]) {
          MAP_MARKER_EXTENDS[MAP_DETAIL_ALEVEL[0]].map((item) => {
            item.$destroy()
          })
          MAP_MARKER_EXTENDS[MAP_DETAIL_ALEVEL[0]] = []
        }
      }
      // clearLevel <= 0 不清除
      if (clearLevel <= 0) {
        return false
      }
      // 覆盖物 清除 { 1: { normal: [], cluster: [], heatmap:[] }, 2: {}, 3: {}, 999: detail }
      for (const key in MAP_OVERFLOWS) {
        // key级别 <= clearLevel 则需要删除
        if (key <= clearLevel) {
          // MAP_DEFAULT_LEVEL_TYPES ['normal', 'cluster', 'heatmap']
          // 普通覆盖物
          if (MAP_OVERFLOWS[key][MAP_DEFAULT_LEVEL_TYPES[0]]?.length > 0) {
            MAP_INSTANCE.remove(MAP_OVERFLOWS[key][MAP_DEFAULT_LEVEL_TYPES[0]])
            MAP_OVERFLOWS[key][MAP_DEFAULT_LEVEL_TYPES[0]] = []
          }
          // 聚合
          if (MAP_OVERFLOWS[key][MAP_DEFAULT_LEVEL_TYPES[1]]?.length > 0) {
            MAP_OVERFLOWS[key][MAP_DEFAULT_LEVEL_TYPES[1]].map((item) => {
              item.setMap(null)
              item = null
            })
            MAP_OVERFLOWS[key][MAP_DEFAULT_LEVEL_TYPES[1]] = []
          }
          // 热力图
          if (MAP_OVERFLOWS[key][MAP_DEFAULT_LEVEL_TYPES[2]]?.length > 0) {
            MAP_OVERFLOWS[key][MAP_DEFAULT_LEVEL_TYPES[2]].map((item) => {
              item.setMap(null)
              item = null
            })
            MAP_OVERFLOWS[key][MAP_DEFAULT_LEVEL_TYPES[2]] = []
          }
        }
      }
      // 清除 marker vue实例
      for (const key in MAP_MARKER_EXTENDS) {
        if (key <= clearLevel) {
          MAP_MARKER_EXTENDS[key].map((item) => {
            item.$destroy()
          })
          MAP_MARKER_EXTENDS[key] = []
        }
      }
    }
  }
}
